﻿using System;
using System.Web.Security;
using FluentValidation;
using FluentValidation.Results;
using GiveAQuiz.Web.Helpers;
using GiveAQuiz.Web.Models;
using GiveAQuiz.Web.Membership;

namespace GiveAQuiz.Web.Validation
{
  /// <summary>
  /// Validates the ConfirmRegistrationViewModel
  /// </summary>
  public class ConfirmRegistrationValidator : AbstractValidator<ConfirmRegistrationViewModel>
  {
    /// <summary>
    /// Creates an instance of the ConfirmRegistrationValidator
    /// </summary>
    /// <param name="membershipSvc">The IMembershipService interface which is used
    /// to perform authentication.</param>
    public ConfirmRegistrationValidator(IMembershipService membershipSvc)
    {
      MembershipService = membershipSvc;

      RuleFor(cr => cr.UserName).NotBlank().WithMessage("Username is required");
      RuleFor(cr => cr.UserName)
        .Must(userName => membershipSvc.GetUser(userName) != null)
        .When(cr => !String.IsNullOrWhiteSpace(cr.UserName))
        .WithMessage("Could not find a user with user name: {0}", cr => cr.UserName);

      Custom(ValidateToken);
    }

    public IMembershipService MembershipService
    {
      get;
      private set;
    }

    /// <summary>
    /// Custom validator method used to validate the token passed back with
    /// the attempt to register the account.
    /// </summary>
    /// <param name="model">The ConfirmRegistrationViewModel object.</param>
    /// <returns>a ValidationFailure if the token cannot be validated;
    /// otherwise null</returns>
    private ValidationFailure ValidateToken(ConfirmRegistrationViewModel model)
    {
      if (!String.IsNullOrWhiteSpace(model.UserName))
      {
        if (String.IsNullOrWhiteSpace(model.Token))
        {
          // missing token
          return new ValidationFailure("Token",
            "In order to confirm this account, you need to provide the " +
            "registration token that was included in the verification URL.");
        }

        MembershipUser user = MembershipService.GetUser(model.UserName);

        // sha the email to match against the token
        string sha1Email = user.Email.ToSHA1Hash().Replace("-", String.Empty);

        if (!model.Token.Equals(sha1Email))
        {
          // wrong token
          return new ValidationFailure("Token",
            "In order to confirm this account, you need to provide the " +
            "registration token that was included in the verification URL.");
        }
      }

      return null;
    }
  }
}